<?php

namespace app\controller;

use app\BaseController;
use EasyWeChat\Factory;
use think\facade\Config;

class Wechat extends BaseController
{

    public function getConfig(): array
    {
        $wechat = Config::get('wechat');
        return [
            'app_id' => $wechat['app_id'],
            'secret' => $wechat['secret'],
            'mch_id' => $wechat['pay']['mch_id'],
            'key' => $wechat['pay']['v2_key'],
            'cert_path' => $wechat['pay']['cert_path'],
            'key_path' => $wechat['pay']['key_path'],
            'notify_url' => $wechat['pay']['notify_url'],
        ];
    }

    /**
     * 生产不重复的随机字符串
     */
    public function createNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return date('Ymd') . $str;
    }

    /**
     * 获取用户openid
     *
     */
    public function getOpenid()
    {
        $code = $this->request->param('code');
        if ($code) {
            // 创建微信小程序对象
            $wechat = Factory::miniProgram($this->getConfig());
            // 获取 session_key 和 openid
            $result = $wechat->auth->session($code);
            // 处理结果
            if (isset($result['openid'])) {
                // 业务处理
                return json(['code' => 1, 'data' => $result['openid'], 'msg' => '获取openid成功']);
            } else {
                // 报错 $res['errmsg']
                return json(['code' => 0, 'data' => '', 'msg' => $result['errmsg']]);
            }
        } else {
            return json(['code' => 0, 'data' => '', 'msg' => 'code不能为空']);
        }
    }

    /**
     * 获取用户手机号
     *
     */
    public function getPhoneNumber()
    {
        $phone_code = $this->request->param('phone_code');
        if ($phone_code) {
            $wechat = Factory::miniProgram($this->getConfig());
            $result = $wechat->phone_number->getUserPhoneNumber($phone_code);
            if (isset($result['phone_info'])) {
                // 业务处理
                return json(['code' => 1, 'data' => $result['phone_info']['phoneNumber'], 'msg' => '获取手机号成功']);
            } else {
                // 报错 $res['errmsg']
                return json(['code' => 0, 'data' => '', 'msg' => $result['errmsg']]);
            }
        } else {
            return json(['code' => 0, 'data' => '', 'msg' => 'phone_code不能为空']);
        }
    }

    /**
     * 微信支付
     */
    public function pay()
    {
        $open_id = $this->request->param('open_id');
        if ($open_id) {
            // 创建微信支付对象
            $wechat = Factory::payment($this->getConfig());
            // 组装请求参数
            $params = [
                'body' => '1分钱支付测试',                                // 商品描述
                'out_trade_no' => $this->createNonceStr(10),     // 商户订单号
                'total_fee' => 1,                                       // 订单总金额，单位为分，只能为整数
                'spbill_create_ip' => '',                               // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
                'notify_url' => 'https://你的线上地址/index.php/wechat/notify',     // 支付结果通知网址，如果不设置则会使用配置里的默认地址
                'trade_type' => 'JSAPI',                                // 请对应换成你的支付方式对应的值类型
                'openid' => $open_id,
            ];
            // 发起支付请求
            $result = $wechat->order->unify($params);
            // 处理支付结果
            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
                // 根据$result中的prepay_id生成签名等信息
                // 将生成的信息返回给前端进行支付
                $response = $wechat->jssdk->bridgeConfig($result['prepay_id'], false); // 返回数组
                return json(['code' => 1, 'data' => $response, 'msg' => '微信支付成功']);
            } else {
                // 支付失败，处理错误信息
                return json(['code' => 0, 'data' => $result, 'msg' => '微信支付失败']);
            }
        } else {
            return json(['code' => 0, 'data' => '', 'msg' => 'open_id不能为空']);
        }
    }

    /**
     * 查询订单
     */
    public function checkOrder()
    {
        $out_trade_no = $this->request->param('out_trade_no');
        $transaction_id = $this->request->param('transaction_id');
        // 创建微信支付对象
        $wechat = Factory::payment($this->getConfig());
        if ($out_trade_no) {
            // 查询订单
            $result = $wechat->order->queryByOutTradeNumber($out_trade_no);
            // 处理查询结果
            if (isset($result['trade_state']) && $result['trade_state'] == 'SUCCESS') {
                return json(['code' => 1, 'data' => $result, 'msg' => '查询订单成功']);
            } else {
                return json(['code' => 0, 'data' => $result, 'msg' => '查询订单失败']);
            }
        } elseif ($transaction_id) {
            // 查询订单
            $result = $wechat->order->queryByTransactionId($transaction_id);
            if (isset($result['trade_state']) && $result['trade_state'] == 'SUCCESS') {
                return json(['code' => 1, 'data' => $result, 'msg' => '查询订单成功']);
            } else {
                return json(['code' => 0, 'data' => $result, 'msg' => '查询订单失败']);
            }
        } else {
            return json(['code' => 0, 'data' => '', 'msg' => 'out_trade_no不能为空']);
        }
    }

    /**
     * 微信退款
     */
    public function refund()
    {
        $out_trade_no = $this->request->param('out_trade_no');
        $transaction_id = $this->request->param('transaction_id');
        $total_fee = $this->request->param('total_fee');
        $refund_fee = $this->request->param('refund_fee');
        if (($out_trade_no || $transaction_id) && $total_fee && $refund_fee) {
            // 生成商户退款单号
            $refund_no = $this->createNonceStr(10);
            // 微信支付金额单位为分，需要*100
            $total_fee = $total_fee * 100;
            // 微信退款金额单位为分，需要*100
            $refund_fee = $refund_fee * 100;
            // 创建微信支付对象
            $wechat = Factory::payment($this->getConfig());
            if ($out_trade_no) {
                // 商户订单号退款，参数分别为：微信订单号、商户退款单号、订单金额、退款金额
                $result = $wechat->refund->byOutTradeNumber($out_trade_no, $refund_no, $total_fee, $refund_fee);
            } else {
                // 微信订单号退款，参数分别为：微信订单号、商户退款单号、订单金额、退款金额
                $result = $wechat->refund->byTransactionId($transaction_id, $refund_no, $total_fee, $refund_fee);
            }
            // 处理退款结果
            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
                // 退款成功，更新订单状态
                return json(['code' => 1, 'data' => $result, 'msg' => '微信退款成功']);
            } else {
                return json(['code' => 0, 'data' => $result, 'msg' => '微信退款失败']);
            }
        } else {
            return json(['code' => 0, 'data' => '', 'msg' => '缺少必要参数']);
        }
    }

    /**
     * 微信支付通知
     *
     */
    public function notify()
    {
        trace('这是一条支付回调日志信息', 'notice');
        $wechat = Factory::payment($this->getConfig());
        $response = $wechat->handlePaidNotify(function ($message, $fail) {
            trace($message, 'notice');
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            $order = '查询数据库';

            if (!$order) { // 如果订单不存在 或者 订单已经支付过了
                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }
            ///////////// <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况，确认是已经支付 /////////////
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    // 支付成功，更新订单状态

                    return true; // 返回处理完成
                } elseif ($message['result_code'] === 'FAIL') {
                    // 用户支付失败

                    return false;
                }
            } else {
                return $fail('通信失败，请稍后再通知我');
            }
        });
        $response->send(); // return $response;
        trace($response, 'notice');
        return $response;
    }

}
